package com.chinaztt.fda.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class EncryptUtil {

	public EncryptUtil() {}
	private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
			.toCharArray();

	/**
	 * strSrc:待加密的内容
	 * encName :MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512 
	 * */
	public static String Encrypt(String strSrc,String encName) {
		MessageDigest md=null;
		String strDes=null;

		byte[] bt=strSrc.getBytes();
		try {
			if (encName==null||encName.equals("")) {
				encName="MD5";
			}
			md=MessageDigest.getInstance(encName);
			md.update(bt);
			strDes=bytes2Hex(md.digest());
		}
		catch (NoSuchAlgorithmException e) {
			return null;
		}
		return strDes;
	}

	public static String bytes2Hex(byte[]bts) {
		String des="";
		String tmp=null;
		for (int i=0;i<bts.length;i++) {
			tmp=(Integer.toHexString(bts[i] & 0xFF));
			if (tmp.length()==1) {
				des +="0";
			}
			des +=tmp;
		}
		return des;
	}

	/**
	 * 根据传递的密钥对明文进行加密
	 *
	 * @param plainText
	 *            明文
	 * @param key
	 *            密钥
	 * @return 密文
	 */
	public static String doDESEncode(String plainText, String key) {
		// 密文
		String cipherText = null;

		byte[] keyByte = key.getBytes();
		byte[] inputData = plainText.getBytes();
		try {

			inputData = encrypt(inputData, BASE64Encoder(keyByte));
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			cipherText = BASE64Encoder(inputData);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return cipherText;

	}

	/**
	 * 根据传递的密文以及密钥进行DES解密
	 *
	 * @param cipherText
	 * @param key
	 * @return
	 */
	public static String doDESDecode1(String key,String cipherText) {
		byte[] keyByte = key.getBytes();
		byte[] output = null;
		try {
			output = decrypt(BASE64Decoder(cipherText), BASE64Encoder(keyByte));
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (output == null) {
			return "";
		}
		return new String(output);
	}


	public static String BASE64Encoder(byte[] data) {
		int start = 0;
		int len = data.length;
		StringBuffer buf = new StringBuffer(data.length * 3 / 2);

		int end = len - 3;
		int i = start;
		int n = 0;

		while (i <= end) {
			int d = (((data[i]) & 0x0ff) << 16)
					| (((data[i + 1]) & 0x0ff) << 8)
					| ((data[i + 2]) & 0x0ff);

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append(legalChars[(d >> 6) & 63]);
			buf.append(legalChars[d & 63]);

			i += 3;

			if (n++ >= 14) {
				n = 0;
				//buf.append(" ");
			}
		}

		if (i == start + len - 2) {
			int d = (((data[i]) & 0x0ff) << 16)
					| (((data[i + 1]) & 255) << 8);

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append(legalChars[(d >> 6) & 63]);
			buf.append("=");
		} else if (i == start + len - 1) {
			int d = ((data[i]) & 0x0ff) << 16;

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append("==");
		}

		return buf.toString();
	}

	/**
	 * Decodes the given Base64 encoded String to a new byte array. The byte
	 * array holding the decoded data is returned.
	 */
	public static byte[] BASE64Decoder(String s) {

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			_base64Decode(s, bos);
		} catch (IOException e) {
			throw new RuntimeException();
		}
		byte[] decodedBytes = bos.toByteArray();
		try {
			bos.close();
			bos = null;
		} catch (IOException ex) {
			System.err.println("Error while decoding BASE64: " + ex.toString());
		}
		return decodedBytes;
	}

	private static int _base64Decode(char c) {
		if (c >= 'A' && c <= 'Z')
			return (c) - 65;
		else if (c >= 'a' && c <= 'z')
			return (c) - 97 + 26;
		else if (c >= '0' && c <= '9')
			return (c) - 48 + 26 + 26;
		else
			switch (c) {
				case '+':
					return 62;
				case '/':
					return 63;
				case '=':
					return 0;
				default:
					throw new RuntimeException("unexpected code: " + c);
			}
	}

	private static void _base64Decode(String s, OutputStream os)
			throws IOException {
		int i = 0;

		int len = s.length();

		while (true) {
			while (i < len && s.charAt(i) <= ' ')
				i++;
			if (i == len)
				break;
			int tri = (_base64Decode(s.charAt(i)) << 18)
					+ (_base64Decode(s.charAt(i + 1)) << 12)
					+ (_base64Decode(s.charAt(i + 2)) << 6)
					+ (_base64Decode(s.charAt(i + 3)));
			os.write((tri >> 16) & 255);
			if (s.charAt(i + 2) == '=')
				break;
			os.write((tri >> 8) & 255);
			if (s.charAt(i + 3) == '=')
				break;
			os.write(tri & 255);
			i += 4;
		}
	}

	public static byte[] encrypt(byte[] data, String key) throws Exception {
		Key k = toKey(BASE64Decoder(key));
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, k);
		return cipher.doFinal(data);
	}

	private static Key toKey(byte[] key) throws Exception {
		DESKeySpec dks = new DESKeySpec(key);
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(dks);

		// 当使用其他对称加密算法时，如AES、Blowfish等算法时，用下述代码替换上述三行代码
		// SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
		return secretKey;
	}


	public static byte[] decrypt(byte[] data, String key) throws Exception {
		Key k = toKey(BASE64Decoder(key));

		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, k);

		return cipher.doFinal(data);
	}
}
